package org.NooLab.itexx.co.targets;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.NooLab.itexx.ITexx;
import org.NooLab.itexx.ITexxFactory;
import org.NooLab.itexx.co.CoWorker;
import org.NooLab.itexx.co.CoWorkerIntf;
import org.NooLab.itexx.co.ExtWorker;
import org.NooLab.itexx.co.ExtWorkers;
import org.NooLab.itexx.co.ITexxModuleAppIntf;
import org.NooLab.itexx.co.ITexxModuleExtAppIntf;
import org.NooLab.utilities.files.DFutils;
import org.NooLab.utilities.net.GUID;
 



public class ExtTikaServer  
							implements 
										ITexxModuleExtAppIntf ,
										StarterIntf{

	
	private ITexxFactory itxFactory;
	ITexx iTexx ;
	
	private Process tikaServerProcess;
	private ExtWorkers extWorkers;
	
	private ExtWorker processDef;
	
	
	// ========================================================================
	public ExtTikaServer(ITexxFactory factory, ITexx itx){
		
		iTexx = itx;
		itxFactory = factory;
		
		extWorkers = iTexx.getExtWorkersContainer();
	}
	
	
	// ========================================================================	

	@Override
	public void configure(int basePortNumber, int maxNumberOfConcurrents){
		
		String path ;
		
		processDef = extWorkers.getExtWorker( iTexx ) ;
		
		processDef.setStarterMethod( (StarterIntf)this) ;
		
		processDef.setJarFilename("NooLabTikaServer.jar") ;
		
		processDef.setJarFilePath("/bin"); // relative to system root   
		
		
		
	    							path = extWorkers.fileutil.createpath( itxFactory.getSystemRootDir(),
	    																   "app/TikaServer");
	    processDef.setAppWorkingDir( path) ; // relative to system root 
	
		
		processDef.setEffectiveClientPort(0);
		 
		processDef.addArgument( "-homedir:\""+path+"\""); 
		
		processDef.addArgument( "-context:itexx"); 
		
	    						String instanceGuid = GUID.randomvalue() ;
	    processDef.setInstanceGuid(instanceGuid);
		processDef.addArgument( "-waitfor:0");
		processDef.addArgument( "-appsecret:"+instanceGuid); 
		processDef.addArgument( "-name:_tikaserver_"); // we use a small decoration
	
		            // we need a central catalog for all ports... from which they are issued
		            // such we build a map 
					extWorkers.lastPort = basePortNumber;
					int port = extWorkers.getNextPort( instanceGuid );
					String portStr = "in-"+port+",out-"+(port+1); // NOT the server port of iTexx !!! (CoWorkerIntf._mainServerPort)
					processDef.setProposedPort(port); // this we need to send a release during startup
		           
		processDef.addArgument( "-comm:"+ portStr);
		
		
		
		processDef.addArgument( "-loglevel:2"); 		
		processDef.setName( this.getClass().getSimpleName() );
	
		
		processDef.setStatus( CoWorkerIntf._CO_STATUS_DEFINED );
		extWorkers.add( processDef ) ;
		
	}


	@Override
	public void start() throws Exception{
		 
		// processDef.launch() ;
		
		// startExternalTikaServer(7202,7201,"") ; // TODO make these port numbers dynamic from config file ...
		// texx understands this CLI argument: -tika: in-7201,out-7202
	
	}

	
 
	
	@Override
	public void startingCall(ExtWorker extWorker) {
		// a facade method for the purpose of standardization
	
		try {
			
			startExternalTikaServer(extWorker);
			
		} catch (InterruptedException e) {
			 
			e.printStackTrace();
		}
	}


	/**
	 * 
	 * the send port could be set adhoc, yet, the "other side" should listen on it
	 * 
	 * @param listenport
	 * @param sendport
	 * @throws InterruptedException 
	 */
	public void startExternalTikaServer(ExtWorker processDef) throws InterruptedException {
		
		
		String appsecret,name,homedir ;
		String ports,argumentStr;
		
		// ports = " in-"+listenport+",out-"+sendport;
		
		ports = processDef.getArgumentByTopic("-comm") ;
				// processDef.addArgument( "-comm:"+ portStr);
		
		appsecret = processDef.getArgumentByTopic("-appsecret") ;
		name      = processDef.getArgumentByTopic("-name") ;
		homedir   = processDef.getArgumentByTopic("-homedir") ;
		
		
		try {
			
			/*
				-homedir:"D:/data/iTexx/app/TikaServer"
				-comm: in-7251,out-7210
				-waitfor:0
				-appsecret: 12ahf-23487asdf-3487sdfr-559
				-name:tikasrv
				-loglevel:2	 
			 */
			
			String path = itxFactory.getSystemRootDir() ;
			path = DFutils.createPath(path, "bin/NooLabTikaServer.jar");
	
			argumentStr =  ports+" -waitfor:0  "+
								   homedir+"  "+
					               appsecret+"  "+
					               name +" "+ // "-name:tikasrv  "+
					               "-loglevel:2" ;
			
			// TODO this is different on different platforms
			// mac osx folder action: Runtime.getRuntime().exec(new String[] { "open", instFolder.toString() })
			// we probably need the full path to java, which we get by System.property  java.home
			// windows TODO better use String[] instead of a string...
            Process extProcess = Runtime.getRuntime().exec("cmd /c start  "+path+"  "+argumentStr);

			StreamGobbler errorGobbler = new StreamGobbler(extProcess.getErrorStream(), "ERR  ");

			// any output?
			StreamGobbler outputGobbler = new StreamGobbler(extProcess.getInputStream(), "---");

			// kick them off
			errorGobbler.start();
			outputGobbler.start();
			
			int exitVal = extProcess.waitFor();
			System.out.println("ExitValue: " + exitVal);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	@Override
	public ExtWorker getProcessDef() {
		return processDef;
	}
	
}



class StreamGobbler extends Thread {
	InputStream is;
	String type;

	StreamGobbler(InputStream is, String type) {
		this.is = is;
		this.type = type;
	}

	public void run() {
		
		try {
			InputStreamReader isr = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
				System.out.println(type + "[x] " + line);
			}

		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
}